<template>
  <component
    :is="'el-form'"
    v-bind="theOptions.form"
    :disabled="formDisabled"
    ref="FyhFormRef"
    :model="model"
    :class="{ flexForm: theOptions.form.inline }"
    :rules="theRules"
  >
    <template v-for="item in theOptions.columns">
      <el-row :gutter="gutter">
        <el-col v-for="(v, i) in item" :span="v.span" :key="i">
          <component :is="'el-form-item'" v-bind="v.formItem">
            <template #label v-if="v.formItem.slotContent">
              <div class="FlexBox gap-6">
                <el-tooltip class="box-item" effect="dark" :content="v.formItem.slotContent" :placement="`top-start`">
                  <el-icon><QuestionFilled /></el-icon>
                </el-tooltip>
                {{ v.formItem.label }}
              </div>
            </template>
            <slot v-if="v.slot" :name="v.slot" :val="model"></slot>
            <template v-else>
              <component
                :is="`el-${v.typeName}`"
                v-bind="v.attrs"
                :model-value="v.formItem.prop.split('.').reduce((result, key) => result?.[key], model)"
                @update:model-value="setItemValue(v.formItem.prop, $event)"
                v-on:[v.methods!.event]="(...val: any) => handleEmit(val, v)"
              >
                <component
                  :is="tagOptions[v.typeName as keyof typeof tagOptions]"
                  v-for="dict in dictMaps[v.dict!]"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                  >{{ dict.label }}
                </component>
              </component>
            </template>
          </component>
        </el-col>
      </el-row>
    </template>
    <!-- <el-row :gutter="gutter">
      <template v-if="DICT.projectData">
        <slot name="form-item-extra" :select="DICT"> </slot>
      </template>
    </el-row> -->
  </component>
</template>

<script setup lang="ts" name="fyh-form">
import { loadModule } from "@/utils/index";
import { useDict } from "@/hooks/dict";
import { ElTooltip, type FormInstance, ElRow, ElCol } from "element-plus";
import { QuestionFilled } from "@element-plus/icons-vue";
const theRules = ref({});
const FyhFormRef = ref<FormInstance>();
interface baseProps {
  modelValue: {
    [key: string]: any;
  }; // 表单数据
  disabled?: boolean; // 是否禁用表单
  modulePath?: string; // 表单配置项模块路径
  needLoadTableDict?: boolean; // 是否需要加载字典
  gutter?: number; // 表单列间距
  fileName?: string; // 所需要加载的文件中导出的配置项对象名字 默认default
  formOptions?: FyhComOptions;
}
interface theEmitType {
  "update:disabled": [val: boolean];
  "update:modelValue": [val: Object];
  handleChange: [val: any];
  [key: string]: [val: any];
}
const dictMaps = ref<any>({});
const tagOptions = {
  select: "el-option",
  "checkbox-group": "el-checkbox",
  "radio-group": "el-radio"
};
const props = withDefaults(defineProps<baseProps>(), {
  needLoadTableDict: false,
  gutter: 10,
  fileName: "default",
  disabled: false
});
if (!props.formOptions && !props.modulePath) {
  console.warn("[fyh-form Component] 至少需要提供 modulePath 或 formOptions 中的一个。");
}
const theEmit = defineEmits<theEmitType>();
const theOptions = ref<FyhComOptions>({
  form: {},
  columns: []
});
/**
 * 动态表单禁用
 * @type {boolean}
 * @description 通过 v-model:disabled 双向绑定
 * @example <fyh-form v-model:disabled="xxx" />
 */
const formDisabled = computed({
  get: () => props.disabled,
  set: (val: boolean) => theEmit("update:disabled", val)
});

const model = computed({
  get: () => props.modelValue,
  set: (val: any) => theEmit("update:modelValue", val)
});
const setItemValue = (prop: string, val: any) => {
  const keys = prop.split(".");
  const lastKey = keys.pop() as string;
  const nestedObj = keys.reduce((obj, key) => {
    if (!obj[key]) obj[key] = {};
    return obj[key];
  }, model.value);
  nestedObj[lastKey] = val;
};
const handleEmit = (val: any, row: elComAttrAndFunType) => {
  theEmit(row.methods!.name!, val);
};
const getDictData = () => {
  if (theOptions.value.dicts!.length > 0) {
    dictMaps.value = useDict(...theOptions.value.dicts!);
  }
  if (theOptions.value.countInter!.length > 0) {
    for (const k of theOptions.value.countInter!) {
      Array.isArray(k) && (dictMaps.value[k[0].dict] = k);
    }
  }
  console.log(dictMaps.value);
};
const initOptions = async () => {
  if (props.modulePath) {
    const res = <EmptyObjectType<FyhComOptions>>await loadModule(props.modulePath);
    theOptions.value = res[props.fileName] || {};
  } else {
    console.log(props.formOptions, "props.formOptions");
    theOptions.value = props.formOptions!;
  }
  theRules.value = theOptions.value.rules ? theOptions.value.rules(model.value) : {};
  getDictData();
  console.log(theOptions.value);
};
defineExpose({
  FyhFormRef,
  theOptions
});
onBeforeMount(initOptions);
</script>

<style lang="scss" scoped>
.el-form {
  :deep(.el-form-item) {
    margin-right: 0px;

    .el-form-item__content > div {
      width: 100%;
    }
  }
}

.flexForm {
  :deep(.el-form-item.is-required) {
    margin-bottom: 18px !important;
  }

  :deep(.el-form-item) {
    margin-bottom: 10px;
    width: 100%;
    display: flex;

    .el-form-item__content {
      flex: 1;
    }

    .el-form-item__label {
      font-size: 12px;
    }
  }
}
</style>
